﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;

namespace Rem.Objects.Forms
{
    public class RemComboBox : ComboBox
    {
        private ErrorProvider _errorProvider;
        private bool _allowEmpty;
        private string _selectionAtEnter;
        private const int WM_KEYDOWN = 0x100;

        // Events
        public event RemComboBoxGotFocusEventHandler RemComboBoxGotFocus;

        public event RemComboBoxLostFocusEventHandler RemComboBoxLostFocus;

        //public event SelectionChangeCommittedEventHandler SelectionChangeCommitted;

        // Methods
        public RemComboBox()
        {
            base.Enter += new EventHandler(this.ComboBox_Enter);
            base.MouseClick += new MouseEventHandler(this.ComboBox_MouseClick);
            base.Validating += new CancelEventHandler(this.ToddComboBox_Validating);
            base.KeyDown += new KeyEventHandler(this.ComboBox_KeyDown);
            this._allowEmpty = false;
            this.AutoCompleteMode = AutoCompleteMode.SuggestAppend;
            this.AutoCompleteSource = AutoCompleteSource.ListItems;
        }

        private void ComboBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (this.DropDownStyle != ComboBoxStyle.DropDownList)
            {
                this.DroppedDown = false;
            }
        }

        private bool ContentValidated()
        {
            string s = this.Text.Trim();
            if (this._selectionAtEnter == s)
            {
                return false;
            }
            if (string.IsNullOrEmpty(s) && this.AllowEmpty)
            {
                if (this._errorProvider == null)
                {
                    this._errorProvider = new ErrorProvider();
                }
                this._errorProvider.SetError(this, "");
                return true;
            }
            int idx = this.FindStringExact(s);
            if (idx == -1)
            {
                if (this._errorProvider == null)
                {
                    this._errorProvider = new ErrorProvider();
                }
                this._errorProvider.SetIconAlignment(this, ErrorIconAlignment.MiddleLeft);
                this._errorProvider.SetError(this, "Must select an item from the dropdown.");
                return true;
            }
            this.SelectedIndex = idx;
            if (this._errorProvider != null)
            {
                this._errorProvider.SetError(this, "");
            }
            return true;
        }

        protected override void Dispose(bool disposing)
        {
            if (this._errorProvider != null)
            {
                this._errorProvider.Dispose();
            }
            base.Dispose(disposing);
        }

        private void ComboBox_Enter(object sender, EventArgs e)
        {
            this._selectionAtEnter = this.Text;
        }

        private void ComboBox_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                this.DroppedDown = true;
            }
        }

        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
            if (this.RemComboBoxGotFocus != null)
            {
                this.RemComboBoxGotFocus(this, e);
            }
        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);
            if (this.RemComboBoxLostFocus != null)
            {
                RemComboBoxLostFocus(null, e);
            }
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (((msg.Msg == 0x100) && ((keyData == Keys.Tab) || (keyData == Keys.Return))) && this.ContentValidated())
            {
                EventArgs e = new EventArgs();
                this.OnSelectionChangeCommitted(e);
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }


        private void ToddComboBox_Validating(object sender, CancelEventArgs e)
        {
            if (!this.ContentValidated())
            {
            }
        }

        // Properties
        public bool AllowEmpty
        {
            get
            {
                return this._allowEmpty;
            }
            set
            {
                this._allowEmpty = value;
            }
        }

        // Nested Types
        public delegate void RemComboBoxGotFocusEventHandler(object sender, EventArgs e);

        public delegate void RemComboBoxLostFocusEventHandler(object sender, EventArgs e);

        //public delegate void SelectionChangeCommittedEventHandler(object sender, EventArgs e);


    }
}
